# +----------------------------------------------------------------------
# | ChatWork智能聊天办公系统
# +----------------------------------------------------------------------
# | 软件声明: 本系统并非自由软件,未经授权任何形式的商业使用均属非法。
# | 版权保护: 任何企业和个人不允许对程序代码以任何形式任何目的复制/分发。
# | 授权要求: 如有商业使用需求,请务必先与版权所有者取得联系并获得正式授权。
# +----------------------------------------------------------------------
# | Author: ChatWork Team <2474369941@qq.com>
# +----------------------------------------------------------------------
import json
from typing import Dict
from tortoise import fields
from kernels.model import DbModel
from common.enums.models import ModelsEnum


class DevLinksModel(DbModel):
    id = fields.IntField(pk=True, unsigned=True, description="主键")
    title = fields.CharField(null=False, max_length=200, default="", description="友链名称")
    image = fields.CharField(null=False, max_length=250, default="", description="友链图标")
    target = fields.CharField(null=False, max_length=250, default="", description="跳转方式")
    url = fields.CharField(null=False, max_length=250, default="", description="跳转链接")
    sort = fields.IntField(null=False, default=0, description="排序编号")
    is_disable = fields.SmallIntField(null=False, default=0, description="是否禁用: [0=否, 1=是]")
    is_delete = fields.SmallIntField(null=False, default=0, description="是否删除: [0=否, 1=是]")
    create_time = fields.IntField(null=False, default=0, description="创建时间")
    update_time = fields.IntField(null=False, default=0, description="更新时间")
    delete_time = fields.IntField(null=False, default=0, description="删除时间")

    class Meta:
        table_description = "友链管理表"
        table = DbModel.table_prefix("dev_links")


class DevDiyModel(DbModel):
    id = fields.IntField(pk=True, unsigned=True, description="主键")
    admin_id = fields.IntField(null=False, default=0, description="管理员ID")
    scene = fields.SmallIntField(null=False, default=0, description="场景")
    name = fields.CharField(null=False, max_length=100, default="", description="名称")
    data = fields.TextField(null=False, default="", description="数据")
    create_time = fields.IntField(null=False, default=0, description="创建时间")
    update_time = fields.IntField(null=False, default=0, description="更新时间")

    class Meta:
        table_description = "友链管理表"
        table = DbModel.table_prefix("dev_diy")


class DevPayConfigModel(DbModel):
    id = fields.IntField(pk=True, unsigned=True, description="主键")
    channel = fields.SmallIntField(null=False, default=0, description="渠道编号: [1=余额,2=微信,3=支付宝]")
    shorter = fields.CharField(null=False, max_length=32, default="", description="简写名称")
    name = fields.CharField(null=False, max_length=32, default="", description="渠道名称")
    logo = fields.CharField(null=False, max_length=250, default="", description="渠道图标")
    icon = fields.CharField(null=False, max_length=250, default="", description="支付图标")
    params = fields.TextField(default="", description="支付配置")
    sort = fields.IntField(null=False, default=0, description="排序编号")
    status = fields.SmallIntField(null=False, default=0, description="渠道状态: [0=禁用, 1=启用]")
    create_time = fields.IntField(null=False, default=0, description="创建时间")
    update_time = fields.IntField(null=False, default=0, description="更新时间")

    class Meta:
        table_description = "支付配置表"
        table = DbModel.table_prefix("dev_pay_config")


class DevModelsModel(DbModel):
    id = fields.IntField(pk=True, unsigned=True, description="主键")
    scene = fields.CharField(null=False, max_length=100, default="", description="模型场景: [chat,vector,ranking]")
    channel = fields.CharField(null=False, max_length=100, default="", description="模型通道")
    logo = fields.CharField(null=False, max_length=250, default="", description="模型图标")
    mark = fields.CharField(null=False, max_length=100, default="", description="模型标记")
    name = fields.CharField(null=False, max_length=100, default="", description="模型名称")
    intro = fields.CharField(null=False, max_length=100, default="", description="模型描述")
    config = fields.TextField(null=False, default="", description="配置信息")
    models = fields.TextField(null=False, default="", description="模型列表")
    sort = fields.IntField(null=False, default=0, description="模型排序")
    is_builtin = fields.SmallIntField(null=False, default=0, description="系统内置: [0=否, 1=是]")
    is_disable = fields.SmallIntField(null=False, default=0, description="是否禁用: [0=否, 1=是]")
    is_delete = fields.SmallIntField(null=False, default=0, description="是否删除: [0=否, 1=是]")
    create_time = fields.IntField(null=False, default=0, description="创建时间")
    update_time = fields.IntField(null=False, default=0, description="更新时间")
    delete_time = fields.IntField(null=False, default=0, description="删除时间")

    class Meta:
        table_description = "AI模型集表"
        table = DbModel.table_prefix("dev_models")

    @classmethod
    async def check_models(cls, models: str, scene: str):
        """ 验证模型 """
        array = models.split(":")
        marks: str = array[0]
        model: str = array[1] if len(array) >= 2 else ""

        sources = ModelsEnum.get_type_desc(scene)
        results = await cls.filter(scene=scene, mark=marks).first()
        if results is None:
            raise Exception(f"{sources}通道不存在: {marks}")
        if results.is_delete:
            raise Exception(f"{sources}通道已下架: {results.name}")
        if results.is_disable:
            raise Exception(f"{sources}通道已停用: {results.name}")

        model_lists = json.loads(results.models)
        for m in model_lists:
            if m["model"] == model and not m["status"]:
                raise Exception(f"{sources}已被停用: {model}")
            elif m["model"] == model:
                config = json.loads(results.config or "{}")
                config["model"] = m["model"]
                return {
                    "mark": results.mark,
                    "channel": results.channel,
                    "alias": m["alias"],
                    "model": m["model"],
                    "price": m["price"],
                    "config": config
                }

        raise Exception(f"{sources}已不存在: {model}")

    @classmethod
    async def get_model_alias(cls, models, scene: str):
        """
        获取模型别名

        Args:
            models (list): [1:2005, 1:2411]
            scene (str): 场景(chat, vector, ranking)

        Author:
            zero
        """
        marks = list({s.split(':')[0] for s in models})
        lists = await (DevModelsModel
                       .filter(mark__in=marks)
                       .filter(scene=scene)
                       .filter(is_delete=0)
                       .all().values("mark", "name", "models"))

        data = {}
        for item in lists:
            item["models"] = json.loads(item.get("models", "[]"))
            data[item["mark"]] = item

        result = {}
        for m in models:
            mark, model = m.split(":")
            dicts = data.get(mark, {})
            c = {"name": dicts.get("name", ""), "model": ""}
            for item in dicts.get("models", []):
                if model == item.get("model"):
                    c["model"] = item.get("alias")
                    break
            result[m] = c
        return result

    @classmethod
    async def get_model_name_dict(cls, scene: str, marks) -> Dict[str, str]:
        """
        获取模型名称字典映射

        Args:
            scene (str): 场景 (chat, vector, ranking)
            marks (list): [openai, doubao, zhipu, ...]

        Returns:
            dict: {'doubao': '火山豆包', 'zhipu': '智谱清言'}

        Author:
            zero
        """
        lists = await (DevModelsModel
                       .filter(scene=scene)
                       .filter(mark__in=marks)
                       .filter(is_delete=0)
                       .all().values("mark", "name"))

        return {item["mark"]: item["name"] for item in lists}


class DevModelsKeysModel(DbModel):
    id = fields.IntField(pk=True, unsigned=True, description="主键")
    scene = fields.CharField(null=False, max_length=20, default="", description="密钥场景")
    channel = fields.CharField(null=False, max_length=100, default="", description="密钥通道")
    app_id = fields.CharField(null=False, max_length=200, default="", description="APPID")
    api_key = fields.CharField(null=False, max_length=300, default="", description="APIKey")
    api_secret = fields.CharField(null=False, max_length=200, default="", description="APISecret")
    error = fields.TextField(null=False, default="", description="错误原因")
    sort = fields.IntField(null=False, default=0, description="密钥排序")
    is_disable = fields.SmallIntField(null=False, default=0, description="是否禁用: [0=否, 1=是]")
    is_delete = fields.SmallIntField(null=False, default=0, description="是否删除: [0=否, 1=是]")
    create_time = fields.IntField(null=False, default=0, description="创建时间")
    update_time = fields.IntField(null=False, default=0, description="更新时间")
    delete_time = fields.IntField(null=False, default=0, description="删除时间")

    class Meta:
        table_description = "AI密钥池表"
        table = DbModel.table_prefix("dev_models_keys")
